package dao

import (
	"context"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"time"
)

type FollowDao interface {
	// FollowRelationList 获取某人的关注列表
	FollowRelationList(ctx context.Context, follower, offset, limit int64) ([]Follow, error)
	FollowRelationDetail(ctx context.Context, follower int64, followee int64) (Follow, error)
	// CreateFollowRelation 创建联系人
	CreateFollowRelation(ctx context.Context, c Follow) error
	// UpdateStatus 更新状态
	UpdateStatus(ctx context.Context, followee int64, follower int64, status uint8) error
	// CntFollower 统计计算关注自己的人有多少
	CntFollower(ctx context.Context, uid int64) (int64, error)
	// CntFollowee 统计自己关注了多少人
	CntFollowee(ctx context.Context, uid int64) (int64, error)
}
type FollowGormDao struct {
	db *gorm.DB
}

func NewFollowGormDao(db *gorm.DB) FollowDao {
	return &FollowGormDao{db: db}
}
func (f *FollowGormDao) FollowRelationList(ctx context.Context, follower, offset, limit int64) ([]Follow, error) {
	var res []Follow
	err := f.db.WithContext(ctx).
		Where("follower = ? AND status = ?", follower, FollowRelationStatusActive).
		Offset(int(offset)).Limit(int(limit)).
		Find(&res).Error
	return res, err
}

func (f *FollowGormDao) FollowRelationDetail(ctx context.Context, follower int64, followee int64) (Follow, error) {
	var res Follow
	err := f.db.WithContext(ctx).Where("follower = ? AND followee = ? AND status = ?",
		follower, followee, FollowRelationStatusActive).First(&res).Error
	return res, err
}

func (f *FollowGormDao) CntFollower(ctx context.Context, uid int64) (int64, error) {
	var res int64
	err := f.db.WithContext(ctx).Model(&Follow{}).Select("count(follower)").
		Where("follower=? and status=?", uid, FollowRelationStatusActive).Count(&res).Error
	return res, err
}

func (f *FollowGormDao) CntFollowee(ctx context.Context, uid int64) (int64, error) {
	var res int64
	err := f.db.WithContext(ctx).Model(&Follow{}).Select("count(followee)").
		Where("follower=? and status=?", uid, FollowRelationStatusActive).Count(&res).Error
	return res, err
}

func (f *FollowGormDao) CreateFollowRelation(ctx context.Context, follow Follow) error {
	now := time.Now().UnixMilli()
	follow.Utime = now
	follow.Ctime = now
	return f.db.WithContext(ctx).Clauses(clause.OnConflict{
		DoUpdates: clause.Assignments(map[string]any{
			"utime":  now,
			"status": FollowRelationStatusActive,
		}),
	}).Create(&follow).Error
}
func (f *FollowGormDao) UpdateStatus(ctx context.Context, follower, followee int64, status uint8) error {
	now := time.Now().UnixMilli()
	return f.db.WithContext(ctx).Model(&Follow{}).Where("follower=? and followee=?", follower, followee).
		Updates(map[string]any{
			"utime":  now,
			"status": status,
		}).Error
}
